import machine
import sys
import select
import random
import gc
from machine import UART, Timer, I2S, Pin
import espidf
import esp
import lvgl as lv
import lv_utils
import ili9XXX as DISP_DRV
#import ili9XXX as ILI9341
#from ili9XXX import st7789
#import utime as time
import time
import tft_buttons
import _thread
import fs_driver

# 是否开启显示
USE_LVGL = True
USE_BOX = esp.flash_size() == 16777216

if USE_BOX:
    print("board is esp32-s3-box-lite")
    USE_ST7789=True
    USE_ILI9341=False
else:
    print("board is esp32-s3")
    USE_ST7789=False
    USE_ILI9341=True

#USE_ST7789 = esp.flash_size() == 16777216
#USE_ILI9341 = esp.flash_size() == 33554432

# box
if USE_ST7789:
    TFT_MISO = -1
    TFT_MOSI = 6
    TFT_SCK  = 7
    TFT_RST = 48
    TFT_CS  = 5
    TFT_DC  = 4
    TFT_BL  = 45
    TFT_BL_ON = 0

# N32R8
# LCD屏管脚：       {CS,	RESET,	DC,	MOSI,	SCK,	LED} ，
# 接esp32-s3的GPIO：{4,	5,		37,	35,		36,		7}
# ILI9341
# 土  红   橙  黄   绿   蓝 紫  灰    白  黑   ？？
# GND VCC CLK MOSI RES DC BLK MISO CS1 CS2 PEN
# GND VCC 36  35   5   37 7   -1   4   -1  -1
# GND VCC 12  11   5   13 6   14   4   7   8
if USE_ILI9341:
    TFT_SCK  = 12
    TFT_MOSI = 11
    TFT_RST = 5
    TFT_DC  = 13
    TFT_BL  = 6
    TFT_MISO = 14
    TFT_CS  = 4

    TFT_CS2  = 7
    TFT_PEN  = 8

    TFT_BL_ON = 1

#gc.collect()
#print(gc.mem_free())

buttons = tft_buttons.Buttons()

left_btn = buttons.left
right_btn = buttons.right
if USE_BOX:
    ok_btn = buttons.center
    back_btn = buttons.boot
else:
    ok_btn = buttons.boot
    back_btn = buttons.center

if USE_LVGL:
    lv_ver = "%d.%d.%d-%s" % (lv.version_major(), lv.version_minor(), lv.version_patch(), lv.version_info())
    print(lv_ver)

    lv.init()

    print("Load cjk font:")
    fs_drv = lv.fs_drv_t()
    fs_driver.fs_register(fs_drv, 'S')
    #font_cn = lv.font_load("S:assets/font/lv_font_cn.fnt")
    #font_cn = lv.font_load("S:assets/font/opposans_m_16.bin")
    #font_cn = lv.font_load("S:assets/font/opposans_m_8.bin")
    font_cn = lv.font_load("S:assets/font/opposans_m_12_cnlv-123.bin")
    print("Load cjk font ok.")

#init display
if USE_ST7789:
    disp_func = DISP_DRV.st7789
elif USE_ILI9341:
    disp_func = DISP_DRV.ili9341
else:
    print("Please set display.")
    sys.exit()

try:
    disp = disp_func(
            mhz=40,
            miso=TFT_MISO,
            mosi=TFT_MOSI,
            clk=TFT_SCK,
            cs=TFT_CS,
            dc=TFT_DC,
            rst=TFT_RST,
            backlight=TFT_BL,
            # 背光设置，0-开，1-关
            backlight_on=TFT_BL_ON,
            power=-1,
            width=320,
            height=240,
            start_x=0,
            start_y=0,
            # 矫正方向
            rot=DISP_DRV.REVERSE_LANDSCAPE,
            # DMA RAM
            factor=8,
            # DMA RAM
            double_buffer=True,
            #spihost=espidf.VSPI_HOST,
            #spimode=0,
            #color_format=lv.COLOR_FORMAT.NATIVE_REVERSED
    )
except Exception as e:
    machine.WDT(timeout=1000)
    print("Error:", e)
    time.sleep(1)
    sys.exit()

print("disp init ok.")

if USE_LVGL:
    scr = lv.scr_act()
    # 直接使用十六进制颜色值
    #scr.set_style_bg_color(lv.color_hex(0x003a57), lv.PART.MAIN)
    #scr.set_style_bg_color(lv.color_hex(0x003366), lv.PART.MAIN)
    scr.set_style_bg_color(lv.color_hex(0x9fc5e8), lv.PART.MAIN)
    # 使用颜色名称
    #scr.set_style_bg_color(lv.palette_main(lv.PALETTE.YELLOW), lv.PART.MAIN)

    #draw_table()
    #sys.exit()

    if True:
        # 显示png图片
        try:
            with open('images/EPC001.png','rb') as f:
                png_data = f.read()
        except:
            print("Could not find EPC001.jpg")
            sys.exit()

        img_cogwheel_argb = lv.img_dsc_t({
          'data_size': len(png_data),
          'data': png_data
        })

        img1 = lv.img(lv.scr_act())
        img1.set_src(img_cogwheel_argb)
        img1.align(lv.ALIGN.TOP_LEFT, 0, 0)
        img1.set_size(320, 240)
        img1.set_zoom(256)

    #draw_table()
    #sys.exit()

    # 初始化Label
    if False:
        label1 = lv.label(lv.scr_act())
        label1.set_style_text_font(font_cn, 0) # 设置字体
        label1.set_long_mode(lv.label.LONG.WRAP)      # 自动换行
        label1.set_recolor(True)                      # 使用颜色
        label1.set_width(310)                         # 设置宽度
        label1.set_style_text_align(lv.TEXT_ALIGN.LEFT, 0) # 左对齐
        label1.align(lv.TEXT_ALIGN.LEFT, 0, 0)			   # 左对齐
        label1.set_text("#ff0000 Start")

    if True:
        label1 = lv.label(lv.scr_act())
        label1.set_recolor(True)                      # 使用颜色
        #cz_label.set_text("#ff0000 嵌入式系统（Embedded System），\n#00ff00 是一种嵌入机械或电气系统内部、#0000ff 具有专一功能和实时计算性能的计算机系统。")
        label1.set_text("#ff0000 system starting...")
        label1.set_width(250)
        label1.align(lv.ALIGN.CENTER, 75, 100)

        label1.set_style_text_font(font_cn, lv.PART.MAIN | lv.STATE.DEFAULT)
        label1.set_text("#ff0000 按OK开始检测")

    #draw_table()
    #sys.exit()

while ok_btn.value():
    pass

def hide_obj(obj):
    obj.add_flag(lv.obj.FLAG.HIDDEN)

def show_obj(obj):
    obj.clear_flag(lv.obj.FLAG.HIDDEN)

hide_obj(img1)
hide_obj(label1)

# SP02
KEY_NAME_CN={
    "ECG_HR" : "心率",
    "BREATH_FREQ" : "呼吸速率",
    "SNA" : "焦虑指数",
    "SDANN" : "RR 间期平均值标准差",
    "r-MSSD" : "相邻 RR 间期差值均方平方根",
    "SDNN" : "全部窦性心搏 RR 间期(瞬时心率) 的标准差",
    "pNN50" : "相邻 RR 间期之差>50ms 的个数占 总 RR 间期个数的百分比",
    "PPG_HR" : "PPG_HR",
    "LVET" : "左心室射血时间",
    "ARRHYTHMIA" : "ARRHYTHMIA",
    "PAT" : "脉搏波到达时间",
    "QT" : "QT 间期"
}

KEY_NAME_EN={
    "ECG_HR" : "HR",
    "BREATH_FREQ" : "BR",
    "SNA" : "SNA",
    "SDANN" : "SDANN",
    "r-MSSD" : "MSSD",
    "SDNN" : "SDNN",
    "pNN50" : "pNN50",
    "PPG_HR" : "PPG_HR",
    "LVET" : "LVET",
    "ARRHYTHMIA" : "AMIA",
    "PAT" : "PAT",
    "QT" : "QT"
}

KEY_NAME_POS={
    "ECG_HR" : [0,1],
    "BREATH_FREQ" : [0,2],
    "SNA" : [0,3],
    "SDANN" : [0,4],
    "r-MSSD" : [0,5],
    "SDNN" : [0,6],
    "pNN50" : [2,1],
    "PPG_HR" : [2,2],
    "LVET" : [2,3],
    "ARRHYTHMIA" : [2,4],
    "PAT" : [2,5],
    "QT" : [2,6],
}

NAMES=(
    "ECG_HR", #: "心率",
    "BREATH_FREQ", #: "呼吸速率",
    "SNA", #: "焦虑指数",
    "SDANN", #: "RR 间期平均值标准差",
    "r-MSSD", #: "相邻 RR 间期差值均方平方根",
    "SDNN", #: "全部窦性心搏 RR 间期(瞬时心率) 的标准差",
    "pNN50", #: "相邻 RR 间期之差>50ms 的个数占 总 RR 间期个数的百分比",
    "PPG_HR", #: "PPG_HR",
    "LVET", #: "左心室射血时间",
    "ARRHYTHMIA", #: "ARRHYTHMIA",
    "PAT", #: "脉搏波到达时间",
    "QT" #: "QT 间期",
)

if True:
    #style = lv.style_t()
    #style.init()
    #style.set_pad_all(0)
    #style.set_text_letter_space(0)
    #style.set_text_line_space(0)

    table = lv.table(lv.scr_act())
    #table.add_style(style, 0)
    #table.set_style_text_font(lv.font_montserrat_14, 0)

    table.set_size(320, 240)
    table.set_row_cnt(7)
    table.set_col_cnt(4)
    table.set_col_width(0, 90)
    table.set_col_width(1, 65)
    table.set_col_width(2, 90)
    table.set_col_width(3, 65)

    #table.set_cell_value(0, 0, "Name")
    #table.set_cell_value(0, 1, "Val")
    #table.set_cell_value(0, 2, "Name")
    #table.set_cell_value(0, 3, "Val")
    for k in NAMES:
        row,col = KEY_NAME_POS[k]
        print(k ,row, col, KEY_NAME_EN[k])
        table.set_cell_value(col-1, row, KEY_NAME_EN[k])
        table.set_cell_value(col-1, row+1, "0")
    table.set_height(240)
    table.center()
    #table.align(lv.ALIGN.TOP_LEFT, 0, 0)
    #table.set_x(0)

print('table ok')

# EPC串口处理
# 创建一个UART对象，将EPC001:GPIO7<=>RX:11 EPC001:GPIO4<=>RX:13
uart = UART(1, rx=11, tx=13, baudrate=115200)

# 创建一个Timer，使用timer的中断来轮询串口是否有可读数据
#timer = Timer(1)
#timer.init(period=50, mode=Timer.PERIODIC, callback=lambda t: read_uart(uart))


# 解析ECG
def get_ecg(ad, nGain=1, is_new = True):
    if not is_new:
        #ad = 8456213
        dGain = 2.3
        #factor = 1000 * 1.2 * 3.77 / 2^24
        return (ad * dGain * (1000 * 1.2 * 3.77 / 2**24))/nGain
    else:
        return (ad - 2**23) * (1000 * 1.2 / 2**23) / nGain


# 解析PPG
def get_ppg(ad, is_new = True):
    if not is_new:
        #ad = 143916
        Gain = 1.0
        #factor = 1.024/2^24
        return ad * Gain * 1.024/2**24
    else:
        return (ad - 2 ** 23) * (1000 * 1.024 / 2**23)


# 提取数据供显示
def get_show_samples(samples):
    avg = sum(samples) / len(samples)
    return [int(i-avg) for i in samples]

# 制造测试数据
step_count=1
def make_test_data(tmp):
    global step_count

    pos = bytes(tmp[0:-2]).find(b'\x0D')
    ecg_data_tmp = bytes(tmp[1:pos])
    ppg_data_tmp = bytes(tmp[pos+1:-2])

    ecg_ad = int(ecg_data_tmp.decode('ascii'))
    ppg_ad = int(ppg_data_tmp.decode('ascii'))

    if step_count>=0 and step_count < 100:
        step_count = step_count + 1
        ecg_ad = ecg_ad + step_count * 10000
        if step_count == 5000:
            step_count = -1
    else:
        step_count = step_count - 1
        ecg_ad = ecg_ad - step_count * 10000
        if step_count == -5000:
            step_count = 1

    if ecg_ad < 0 :
        ecg_ad = 0

    if random.randint(1,100) > 50:
        ppg_ad = ppg_ad + random.randint(1000,2000) * 1000
    else:
        ppg_ad = ppg_ad - random.randint(1000,2000) * 1000

    if ppg_ad < 0 :
        ppg_ad = 0


    tmp = [0x23] + [ord(char) for char in str(ecg_ad)] + [0x0D] + [ord(char) for char in str(ppg_ad)] + [0x00, 0x0A]

    s = sum(tmp[0:-2]) & 0xFF
    tmp[-2] = s

    return tmp

hide_obj(table)
print('table hide')

#ecg_sample = data_sample.ecg_sample
#ecg_sample = [0 for i in range(1000)]

def slider_x_event_cb(e):

    slider = e.get_target_obj()
    v = slider.get_value()
    chart.set_zoom_x(v)

def slider_y_event_cb(e):

    slider = e.get_target_obj()
    v = slider.get_value()
    chart.set_zoom_y(v)


#
# Display 1000 data points with zooming and scrolling.
# See how the chart changes drawing mode (draw only vertical lines) when
# the points get too crowded.

# 波形数据显示chart
chart = lv.chart(lv.scr_act())
chart.set_size(320, 240)
chart.align(lv.ALIGN.CENTER, 0, 0)
chart.set_range(lv.chart.AXIS.PRIMARY_Y, -1000, 1000)

# 设置不显示数据点，只显示曲线
chart.set_style_size(0, 0, lv.PART.INDICATOR)

ser = chart.add_series(lv.palette_main(lv.PALETTE.RED), lv.chart.AXIS.PRIMARY_Y)

ecg_sample = [0 for i in range(1000)]
pcnt = len(ecg_sample)
pcnt = 1000
chart.set_point_count(pcnt)
chart.set_ext_y_array(ser, ecg_sample)

# ================================

# 初始化Label
label_set = lv.label(lv.scr_act())
label_set.set_recolor(True)                      # 使用颜色
label_set.set_style_text_align(lv.TEXT_ALIGN.LEFT, 0) # 左对齐
label_set.align(lv.TEXT_ALIGN.LEFT, 10, 220)			   # 左对齐
label_set.set_text("#0000ff BS: ON   HP: 1Hz   LP: 15-20Hz  Zoom: 12")

label_status = lv.label(lv.scr_act())
label_status.set_recolor(True)                      # 使用颜色
label_status.set_style_text_align(lv.TEXT_ALIGN.LEFT, 0) # 左对齐
label_status.align(lv.TEXT_ALIGN.LEFT, 10, 0)			   # 左对齐
label_status.set_text("#0000ff [Read]")

label_val = lv.label(lv.scr_act())
label_val.set_recolor(True)                      # 使用颜色
label_val.set_style_text_align(lv.TEXT_ALIGN.LEFT, 0) # 左对齐
label_val.align(lv.TEXT_ALIGN.LEFT, 60, 0)			   # 左对齐
label_val.set_text("#0000ff Raw: 0000000  mV: 0.000000")

chart.set_x(0)
label_set.set_x(10)
label_status.set_x(10)
label_val.set_x(60)

print("chat init ok.")

#show_obj(chart)
#show_obj(label_set)
#show_obj(label_val)
#show_obj(label_status)

#while True:
#    pass

# 测试数据集
data_test = None #[0x23,0x38,0x34,0x30,0x39,0x34,0x37,0x39,0x0D,0x31,0x39,0x30,0x36,0x37,0x32,0x32,0x14,0x0A]

# 基础指令
# 停止采集
cmd_stop = [0x14, 0x00, 0x14, 0x0D]
# 开始采集
cmd_start = [0x14, 0x01, 0x15, 0x0D]
# 设置放大倍数
cmd_ecg_zoom = [0x24, 0x05, 0x29, 0x0D]
# 设置BS过滤开启
cmd_set_bs = [0x17, 0x01, 0x18, 0x0D]
# 设置HP 1Hz
cmd_set_hp = [0x18, 0x02, 0x1A, 0x0D]
# 设置LP 15-20Hz
cmd_set_lp = [0x19, 0x01, 0x1A, 0x0D]

# ECG启停指令
cmd_start_ecg = [0x12, 0x01, 0x13, 0x0D]
cmd_stop_ecg = [0x12, 0x00, 0x12, 0x0D]

# 启动发送停止指令
send_data = cmd_stop
send_bytes = b''.join(map(lambda x:int.to_bytes(x,1,'little'),send_data))
send_string = ' '.join(["%02X" % b for b in send_data])
print("send : ", send_string)
uart.write(send_bytes)

# 启动发送停止指令
send_data = cmd_stop_ecg
send_bytes = b''.join(map(lambda x:int.to_bytes(x,1,'little'),send_data))
send_string = ' '.join(["%02X" % b for b in send_data])
print("send : ", send_string)
uart.write(send_bytes)

time.sleep(0.1)

while True and not data_test:
    l=uart.any()
    if l:
        tmp = uart.read(l)
        data_string = ' '.join(["%02X" % b for b in tmp])
        print("receive: ", data_string)
    else:
        break

# 发送ECG设置
send_data = cmd_ecg_zoom
send_bytes = b''.join(map(lambda x:int.to_bytes(x,1,'little'),send_data))
send_string = ' '.join(["%02X" % b for b in send_data])
print("send : ", send_string)
uart.write(send_bytes)

while True and not data_test:
    l=uart.any()
    if l:
        tmp = uart.read(l)
        data_string = ' '.join(["%02X" % b for b in tmp])
        print("receive: ", data_string)
    else:
        break

# 发送ECG设置
send_data = cmd_set_bs
send_bytes = b''.join(map(lambda x:int.to_bytes(x,1,'little'),send_data))
send_string = ' '.join(["%02X" % b for b in send_data])
print("send : ", send_string)
uart.write(send_bytes)

while True and not data_test:
    l=uart.any()
    if l:
        tmp = uart.read(l)
        data_string = ' '.join(["%02X" % b for b in tmp])
        print("receive: ", data_string)
    else:
        break

# 发送ECG设置
send_data = cmd_set_hp
send_bytes = b''.join(map(lambda x:int.to_bytes(x,1,'little'),send_data))
send_string = ' '.join(["%02X" % b for b in send_data])
print("send : ", send_string)
uart.write(send_bytes)

while True and not data_test:
    l=uart.any()
    if l:
        tmp = uart.read(l)
        data_string = ' '.join(["%02X" % b for b in tmp])
        print("receive: ", data_string)
    else:
        break

# 发送ECG设置
send_data = cmd_set_lp
send_bytes = b''.join(map(lambda x:int.to_bytes(x,1,'little'),send_data))
send_string = ' '.join(["%02X" % b for b in send_data])
print("send : ", send_string)
uart.write(send_bytes)

while True and not data_test:
    l=uart.any()
    if l:
        tmp = uart.read(l)
        data_string = ' '.join(["%02X" % b for b in tmp])
        print("receive: ", data_string)
    else:
        break

# 发送ECG测量指令
send_data = cmd_start_ecg
send_bytes = b''.join(map(lambda x:int.to_bytes(x,1,'little'),send_data))
send_string = ' '.join(["%02X" % b for b in send_data])
print("send : ", send_string)
uart.write(send_bytes)

# 按钮处理
receive_status = 1
def button_process(threadName):
    global buttons,table,chart,label_set,label_val,receive_status,label1

    print("Start thread %s" % threadName)
    prev_button = None
    prev_time = time.time()
    page = 1
    while True:
        key = buttons.button()
        if key:
            if not prev_button == key:
                if key == 'left':
                    receive_status = 1
                    page = 1
                    # 首图+提示
                    hide_obj(img1)
                    hide_obj(label1)
                    # 表格
                    hide_obj(table)
                    # 图表+文字
                    show_obj(chart)
                    show_obj(label_set)
                    show_obj(label_val)
                    show_obj(label_status)
                elif key == 'right':
                    receive_status = 2
                    page = 2
                    # 首图+提示
                    hide_obj(img1)
                    hide_obj(label1)
                    # 表格
                    table.set_x(0)
                    show_obj(table)
                    # 图表+文字
                    hide_obj(chart)
                    hide_obj(label_set)
                    hide_obj(label_val)
                    hide_obj(label_status)
                elif key == 'center':
                    if page == 0:
                        receive_status = 1
                        page = 1
                        # 首图+提示
                        hide_obj(img1)
                        hide_obj(label1)
                        # 表格
                        hide_obj(table)
                        # 图表+文字
                        show_obj(chart)
                        show_obj(label_set)
                        show_obj(label_val)
                        show_obj(label_status)

                        label_status.set_text("#0000ff [Read]")
                    elif page == 1 or page == 2:
                        if receive_status == 3:
                            receive_status = page
                            label_status.set_text("#0000ff [Read]")
                        else:
                            receive_status = 3
                            label_status.set_text("#0000ff [Stop]")
                elif key == 'boot':
                    receive_status = 0
                    page = 0
                    # 首图+提示
                    show_obj(img1)
                    show_obj(label1)
                    # 表格
                    hide_obj(table)
                    # 图表+文字
                    hide_obj(chart)
                    hide_obj(label_set)
                    hide_obj(label_val)
                    hide_obj(label_status)

                prev_time = time.time()
                prev_button = key

                print("button is %s" % key, prev_button, prev_time, receive_status)

                #time.sleep(0.01)

        if time.time() - prev_time > 1 :
            prev_button = None

        time.sleep(0.01)

print("start_new_thread")
_thread.start_new_thread( button_process, ("Thread-button", ) )

time.sleep(0.1)

# 临时数据
counter = 0
data = []
tmp_prev = None

data_more = []
data_string_more = ""

ecg_index = 0
while True:
    if uart.any() or data_test:
        if not data_test:
            tmp = uart.readline()
        else:
            tmp = bytes(make_test_data(data_test))
        if len(tmp)==1:
            tmp_prev = tmp
            continue
        else:
            if tmp_prev:
                tmp = tmp_prev + tmp
                tmp_prev = None

        if counter % 1000 == 0:
            data_string = ' '.join(["%02X" % b for b in tmp])
            print("[%d] receive[len=%d]: %s" % (counter, len(tmp), data_string))

        if tmp[0]==0x23 and tmp[-1]==0x0A:
            #continue
            # 需要数据分析：ECG+PPG
            pos = tmp[0:-2].find(b'\x0D')
            if pos>0:
                if True:
                    s = sum(tmp[0:-2]) & 0xFF
                    if not s == tmp[-2]:
                        debug=False
                        if debug:
                            print("error: sum error got:%02X sum:%02X" % (tmp[-2], s))
                            data_string = ' '.join(["%02X" % b for b in tmp])
                            print(data_string)
                            data_string = ' '.join(["%02X" % b for b in tmp[0:-2]])
                            print(data_string)
                        continue

                    ecg_data_tmp = tmp[1:pos]
                    ppg_data_tmp = tmp[pos+1:-2]

                    ecg_ad = int(ecg_data_tmp.decode('ascii'))
                    ppg_ad = int(ppg_data_tmp.decode('ascii'))
                    ecg_val = get_ecg(ecg_ad, 12)
                    ppg_val = get_ppg(ppg_ad)

                    #print("data[%d]: " % counter, ecg_ad, ppg_ad, ecg_val, ppg_val)

                    ecg_index = ecg_index + 1
                    if len(ecg_sample)>=1000:
                        val = ecg_sample.pop(0)
                    ecg_sample.append(int(ecg_val))
                    #ecg_sample.append(val)

                    if not receive_status == 1:
                        continue

                    if ecg_index % 10 == 0 :
                        label_val.set_text("#0000ff Raw: %d  mV: %0.6f" % (ecg_ad, ecg_val))
                        #print("data[%d]: " % counter, ecg_ad, ppg_ad, ecg_val, ppg_val)
                        chart.set_ext_y_array(ser, get_show_samples(ecg_sample))
                        chart.refresh()


                #except Exception as e:
                #    print("error:", e, tmp[pos+1:-2])
        elif tmp[0]==0x21 and tmp[-1]==0x0A:
            #continue
            # 需要数据分析：ECG
            #data_string = ' '.join(["%02X" % b for b in tmp])
            #print("[%d] receive[len=%d]: %s" % (counter, len(tmp), data_string))

            if True:
                s = sum(tmp[0:-2]) & 0xFF
                if not s == tmp[-2]:
                    debug=False
                    if debug:
                        print("error: sum error got:%02X sum:%02X" % (tmp[-2], s))
                        data_string = ' '.join(["%02X" % b for b in tmp])
                        print(data_string)
                        data_string = ' '.join(["%02X" % b for b in tmp[0:-2]])
                        print(data_string)
                    continue

                ecg_data_tmp = tmp[1:-2]

                try:
                    ecg_ad = int(ecg_data_tmp.decode('ascii'))
                except Exception as e:
                    data_string = ' '.join(["%02X" % b for b in tmp[0:-2]])
                    print("Error:", e, data_string)

                ecg_val_gain = get_ecg(ecg_ad)
                ecg_val = get_ecg(ecg_ad, 12)

                #print("data[%d]: " % counter, ecg_ad, ppg_ad, ecg_val, ppg_val)

                ecg_index = ecg_index + 1
                if len(ecg_sample)>=1000:
                    val = ecg_sample.pop(0)
                #ecg_sample.append(int(ecg_val))
                ecg_sample.append(ecg_ad)
                #ecg_sample.append(val)

                if not receive_status == 1:
                    continue

                if ecg_index % 10 == 0 :
                    label_val.set_text("#0000ff Raw: %d  mV: %0.6f" % (ecg_ad, ecg_val_gain))
                    #print("data[%d]: " % counter, ecg_ad, ecg_val)
                    ecg_sample_show = get_show_samples(ecg_sample)
                    chart.set_range(lv.chart.AXIS.PRIMARY_Y, min(ecg_sample_show)-20, max(ecg_sample_show)+20)
                    chart.set_ext_y_array(ser, ecg_sample_show)
                    chart.refresh()


            #except Exception as e:
            #    print("error:", e, tmp[1:-2])
        elif tmp[0]==0x22 and tmp[-1]==0x0A:
            #continue
            # 需要数据分析：PPG
            #data_string = ' '.join(["%02X" % b for b in tmp])
            #print("[%d] receive[len=%d]: %s" % (counter, len(tmp), data_string))

            if True:
                s = sum(tmp[0:-2]) & 0xFF
                if not s == tmp[-2]:
                    debug=False
                    if debug:
                        print("error: sum error got:%02X sum:%02X" % (tmp[-2], s))
                        data_string = ' '.join(["%02X" % b for b in tmp])
                        print(data_string)
                        data_string = ' '.join(["%02X" % b for b in tmp[0:-2]])
                        print(data_string)
                    continue

                ppg_data_tmp = tmp[1:-2]

                ppg_ad = int(ppg_data_tmp.decode('ascii'))
                ppg_val = get_ppg(ppg_ad)

                #print("data[%d]: " % counter, ecg_ad, ppg_ad, ecg_val, ppg_val)

                ppg_index = ppg_index + 1
                if len(ecg_sample)>=1000:
                    val = ecg_sample.pop(0)
                #ecg_sample.append(int(ecg_val))
                ecg_sample.append(ppg_ad)
                #ecg_sample.append(val)

                if not receive_status == 1:
                    continue

                if ppg_index % 10 == 0 :
                    label_val.set_text("#0000ff Raw: %d  mV: %0.6f" % (ppg_ad, ppg_val))
                    #print("data[%d]: " % counter, ecg_ad, ecg_val)
                    data_sample_show = get_show_samples(ecg_sample)
                    chart.set_range(lv.chart.AXIS.PRIMARY_Y, min(data_sample_show)-20, max(data_sample_show)+20)
                    chart.set_ext_y_array(ser, data_sample_show)
                    chart.refresh()


            #except Exception as e:
            #    print("error:", e, tmp[1:-2])
        elif tmp[0]==0x26 and tmp[-1]==0x0A:
            # 需要数据分析：指数
            s = sum(tmp[0:-2]) & 0xFF
            if not s == tmp[-2]:
                debug=False
                if debug:
                    print("error: sum error got:%02X sum:%02X" % (tmp[-2], s))
                    data_string = ' '.join(["%02X" % b for b in tmp])
                    print(data_string)
                    data_string = ' '.join(["%02X" % b for b in tmp[0:-2]])
                    print(data_string)
                continue

            if not receive_status == 2:
                continue

            pos = tmp[0:-2].find(b'=')
            if pos>0:
                #data_string = ' '.join(["%02X" % b for b in tmp])
                #print(data_string)
                key = tmp[1:pos].decode()
                val = tmp[pos+1:-2]
                val = int(val.decode('ascii'))
                #print("data[%d]: %s=%d" % (counter, key, val))
                #print("Info: More", tmp[0:-2])
                #print(data_string, " sum=%02X" % s)
                if key == "ECG_HR":
                    data_more = []

                data_more.append("%s=%d" % (key, val))
                #label1.set_text("#ff0000 %s" % ','.join(data_more))

                row,col = KEY_NAME_POS[key]
                print(k ,row, col, KEY_NAME_EN[k], val)
                #table.set_cell_value(col, row, KEY_NAME_EN[k])
                table.set_cell_value(col-1, row+1, str(val))
            else:
                data_string = ' '.join(["%02X" % b for b in tmp])
                print("error: " , data_string)

        counter = counter + 1
        if counter==10000000:
            send_data = cmd_stop
            send_bytes = b''.join(map(lambda x:int.to_bytes(x,1,'little'),send_data))
            send_string = ' '.join(["%02X" % b for b in send_data])
            print("send : ", send_string)
            uart.write(send_bytes)
            #break
    else:
        time.sleep(0.01)

print("read end")
